home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 308_02 / virtlist.cpp < prev    next >
C/C++ Source or Header  |  1990-09-20  |  7KB  |  256 lines

  1.  
  2. /*
  3.     TITLE:          C++ virtual doubly-linked list object;
  4.     DESCRIPTION:    "Doubly-linked list object that uses
  5.             dynamic memory and disk space for run-time
  6.             data storage";
  7.  
  8.     VERSION:        1.01;
  9.     DATE:           9/22/90;
  10.     COMPILERS:      Borland Turbo C++ V.1.0;
  11.     KEYWORDS:       virtual list object;
  12.     FILENAME:       VirtList.cpp;
  13.     SEE-ALSO:       VirtList.hpp, dbl_list.hpp;
  14.  
  15.     REQUIRES:    Header and module files for these:
  16.  
  17.                 ***    C++    ***
  18.  
  19.             Class        Header              Source
  20.  
  21.             BaseList    BaseList.hpp    BaseList.cpp
  22.             DoubleList    dbl_list.hpp    dbl_list.cpp
  23.             DiskList    DiskList.hpp    DiskList.cpp
  24.             VirtualList    VirtList.hpp    VirtList.cpp
  25.  
  26.                 *****    C   *****
  27.  
  28.             debug.obj    debug.h        debug.c
  29.  
  30.  
  31.     NOTES:        1) BaseList is a virtual base class, the
  32.                chain of inheritance is from BaseList
  33.                directly down the list to VirtualList.
  34.                Most of the methods are "virtual" so
  35.                external functions you write can use
  36.                a BaseList * as a parameter, and call
  37.                the correct method.  The function
  38.                bfind(), for example, performs a binary
  39.                search on a sorted object derived from
  40.                class BaseList. ( See bfind.cpp ).
  41.  
  42.             2) See the header files for methods available
  43.                to the objects.  VirtualList has just been
  44.                debugged, so documentation is on hold until
  45.                I play with these objects for a while.  I'm
  46.                likely to find a few more significant errors,
  47.                so no need to rush things.
  48.  
  49.             3) The disk storage routines use the tmpfile(),
  50.                fseek(), ftell(), fread() and fwrite() ANSI C
  51.                file functions and should be compatible with
  52.                systems that use a "long int" for file size.
  53.  
  54.             4) The Turbo C++ extensions coreleft(), and
  55.                _stklen are used to determine dynamic memory
  56.                supply.
  57.  
  58.             5) Recommend using this object under MS DOS with
  59.                a "large data" memory model.  I've been using
  60.                the "COMPACT" model during debugging.
  61.  
  62.             6) Debug.c supplies the function err_exit(), used
  63.                for program error termination with optional error
  64.                location information for debugging.
  65.                ( See the macro in Debug.h ).
  66.  
  67.     ENHANCEMENTS:    1) For MS/PC DOS systems, expanded memory could be
  68.                used, if available, before resorting to disk
  69.                access.
  70.  
  71.             2) Checks for available disk space and exception
  72.                handlers should be added to the code for greater
  73.                reliability.
  74.  
  75.             3) tmpname() could be used, instead of tmpfile(),
  76.                so that an argument could be passed to the
  77.                program indicating a "ram disk" to be used
  78.                in place of the default drive.  The sort()
  79.                method is orders of magnitude faster when
  80.                all data items being compared are in memory.
  81.  
  82.     AUTHOR:         Michael Kelly
  83.             254 Gold St. Boston, Ma. 02127
  84.             Copyright 1990;
  85.  
  86.     COPYRIGHT:    This code may not be commercially distributed
  87.             without prior arrangement with the author.  It
  88.             may be used by programmers, without royalty, for
  89.             their personal programs and for "one of a kind"
  90.             or "custom" applications, provided that said
  91.             programmers assume all liability concerning
  92.             same.
  93. */
  94.  
  95.  
  96. #include "virtlist.hpp"
  97.  
  98. void * VirtualList::buff1 = NULL;
  99. void * VirtualList::buff2 = NULL;
  100. size_t VirtualList::buff_references = 0;
  101.  
  102. VirtualList::VirtualList(void)
  103. {
  104.     if(! buff1  &&  ! buff2)
  105.     {
  106.     if(! (buff1 = new char[SIZE_MAX])  ||
  107.        ! (buff2 = new char[SIZE_MAX]))
  108.         err_exit("Not enough dynamic memory for virtual lists");
  109.     }
  110.     buff_references++;
  111. }
  112.  
  113. VirtualList::~VirtualList(void)
  114. {
  115.     if(! --buff_references)  {
  116.     if(buff2)  {
  117.         delete buff2;
  118.         buff2 = NULL;
  119.     }
  120.  
  121.     if(buff1)  {
  122.         delete buff1;
  123.         buff1 = NULL;
  124.     }
  125.     }
  126. }
  127.  
  128. Boolean VirtualList::add_item(void *item, size_t itemsize, Place place)
  129. {
  130.     if(itemsize > SIZE_MAX)  {
  131.     lerror = INV_SIZE;
  132.     return False;
  133.     }
  134.     if(coreleft() > dynamic_min)
  135.     return DoubleList::add_item(item, itemsize, place);
  136.  
  137.     return DiskList::add_item(item, itemsize, place);
  138. }
  139.  
  140. Boolean VirtualList::get_item(void *itembuf)
  141. {
  142.     DiskLink *tmplink;
  143.  
  144.     if(! entries)  {
  145.     lerror = EMPTY_LIST;
  146.     return False;
  147.     }
  148.  
  149.     if(Current->entry->itemsize == sizeof(DiskLink))  {
  150.     tmplink = (DiskLink *)Current->entry->item;
  151.     if(tmplink->dl_id == DL_ID)
  152.         return DiskList::get_item(itembuf);
  153.     else
  154.         return DoubleList::get_item(itembuf);
  155.     }
  156.     else
  157.     return DoubleList::get_item(itembuf);
  158. }
  159.  
  160. size_t VirtualList::get_size(void)
  161. {
  162.     DiskLink *tmplink;
  163.  
  164.     if(! entries)  {
  165.     lerror = EMPTY_LIST;
  166.     return False;
  167.     }
  168.  
  169.     tmplink = (DiskLink *)Current->entry->item;
  170.  
  171.     if(tmplink->dl_id == DL_ID)
  172.     return DiskList::get_size();
  173.     else
  174.     return DoubleList::get_size();
  175. }
  176.  
  177. int VirtualList::compare_item(void *item1)
  178. {
  179.     DiskLink *tmplink;
  180.     int dif;
  181.  
  182.     if(! entries)  {
  183.     lerror = EMPTY_LIST;
  184.     return False;
  185.     }
  186.  
  187.     tmplink = (DiskLink *)Current->entry->item;
  188.  
  189.     if( (Current->entry->itemsize == sizeof(DiskLink)) &&
  190.     (tmplink->dl_id == DL_ID) )
  191.     {
  192.     if(buff2) delete buff2;
  193.     dif = DiskList::compare_item(item1);
  194.     if(! (buff2 = new char[SIZE_MAX]))
  195.         lerror = NO_MEM;
  196.     return dif;
  197.     }
  198.     else
  199.     return DoubleList::compare_item(item1);
  200. }
  201.  
  202. int VirtualList::compare(void *item1, void *item2)
  203. {
  204.     DiskLink *d1, *d2;
  205.     void *an_item;
  206.     int dif;
  207.  
  208.     d1 = (DiskLink *)item1;
  209.     d2 = (DiskLink *)item2;
  210.  
  211.  
  212.     if(d1->dl_id != DL_ID  &&  d2->dl_id != DL_ID)
  213.     return DoubleList::compare(item1, item2);
  214.  
  215.     else if(d1->dl_id == DL_ID  &&  d2->dl_id == DL_ID)  {
  216.     if(buff2) delete buff2;
  217.     if(buff1) delete buff1;
  218.     dif = DiskList::compare(item1, item2);
  219.     if(! (buff1 = new char[SIZE_MAX])  ||
  220.        ! (buff2 = new char[SIZE_MAX]))
  221.         lerror = NO_MEM;
  222.     return dif;
  223.     }
  224.  
  225.     else if(d1->dl_id == DL_ID)  {
  226.     if(buff2) delete buff2;
  227.     an_item = new char[d1->itemsize];
  228.     if(! an_item)  {
  229.         lerror = NO_MEM;
  230.         return 0;
  231.     }
  232.     fseek(fp, d1->itemsize, SEEK_SET);
  233.     fread(an_item, d1->itemsize, 1, fp);
  234.     dif = DoubleList::compare(an_item, item2);
  235.     delete an_item;
  236.     if(! (buff2 = new char[SIZE_MAX]))
  237.         lerror = NO_MEM;
  238.     return dif;
  239.     }
  240.     else  {
  241.     if(buff2) delete buff2;
  242.     an_item = new char[d2->itemsize];
  243.     if(! an_item)  {
  244.         lerror = NO_MEM;
  245.         return 0;
  246.     }
  247.     fseek(fp, d2->itemsize, SEEK_SET);
  248.     fread(an_item, d2->itemsize, 1, fp);
  249.     dif = DoubleList::compare(item1, an_item);
  250.     delete an_item;
  251.     if(! (buff2 = new char[SIZE_MAX]))
  252.         lerror = NO_MEM;
  253.     }
  254.     return dif;
  255. }
  256.